/*
树与图的遍历
时间复杂度 O(n+m), n表示点数，m表示边数
深度优先遍历 模板题 AcWing 846. 树的重心
int dfs(int u)
{
  st[u] = true; // st[u] 表示点u已经被遍历过

  for(int i = h[u]; i!=-1; i=ne[i])
  {
    int j = e[i];  // 找节点u的邻接点j
    if(!st[j]) dfs(j); // 没有遍历则继续遍历

  }
}
*/

/*
 * [842] 算法基础课
 *
 * 给定一个整数n，将数字1~n排成一排，将会有很多种排列方法
 * 现在，请你按照字典序将所有的排列方法输出
 *
 * 输入格式
 * 共一行，包含一个整数n
 *
 * 输出格式
 * 按字典序输出所有排列方案，每个方案占一行
 *
 * 输入样例：
 * 3
 * 输出样例：
 * 1 2 3
 * 1 3 2
 * 2 1 3
 * 2 3 1
 * 3 1 2
 * 3 2 1
 * g++ test_cpp.cpp -ggdb -std=c++11
 */

#include <iostream>
using namespace std;

const int N = 10;

int n;        // 输入n
int path[N];  // 方案记下来,每一条路径
bool st[N];

void dfs(int u)
{
  if (u == n)
  {
    for (int i = 0; i < n; i++) printf("%d", path[i]);
    puts("");  //  每输出一个方案加空行
    return;
  }

  for (int i = 1; i <= n; i++)  // 枚举一下当前位置能够填哪些数，
    if (!st[i])
    {
      path[u] = i;  // 枚举i填到当前位置上去
      st[i] = true;
      dfs(u + 1);
      path[u] = 0;    // 恢复现场
      st[i] = false;  // 恢复现场
    }
}

int main()
{
  cin >> n;
  dfs(0);
  return 0;
}
